package com.service.business.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.service.business.base.service.ConfigService;
import com.service.core.exception.CommonException;
import com.service.dao.constants.ConfigConstants;
import com.service.dao.enums.MemberJAType;
import com.service.dao.model.JournalAccount;
import com.service.dao.model.MemberStore;
import com.service.dao.model.SysConfig;
import com.service.business.member.service.MemberCapitalMeasurementService;
import com.service.business.member.service.MemberJAService;
import com.service.business.member.service.MemberStoreService;
import com.service.utility.modelmapper.ModelMapperUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * <dl>
 * <dt>back-end</dt>
 * <dd>Description:</dd>
 * <dd>Copyright: Copyright (C) 2015</dd>
 * <dd>Company: </dd>
 * <dd>CreateDate: 2019年11月25日</dd>
 * </dl>
 *
 * @author
 */
@Slf4j
@Service
public class MemberCapitalMeasurementServiceImpl implements MemberCapitalMeasurementService {

    @Autowired
    private ConfigService configService;
    @Autowired
    private MemberStoreService storeService;
    @Autowired
    private MemberJAService memberJAService;

    @Override
    public void checkJA(Integer memberId, Integer coinsId) {

        if(!check(memberId, coinsId)){
            throw new CommonException("会员流水异常", "member_business_store_ja_error");
        }
    }

    @Override
    public Boolean check(Integer memberId, Integer coinsId) {

        Map<String, SysConfig> configMap = configService.getConfigMapByGroup(ConfigConstants.Group.Capital_Measurement.getCode());
        if(configMap.containsKey(ConfigConstants.MEMBER_STORE_MEASURE_OPEN) &&
                !StringUtils.equals(configMap.get(ConfigConstants.MEMBER_STORE_MEASURE_OPEN).getConfValue(), ConfigConstants.Value.ACTIVE.getCode())){
            log.info("未开启资金测算");
            return true;
        }

        MemberStore store = storeService.getOne(new QueryWrapper<MemberStore>().lambda()
                .eq(MemberStore::getMemberId, memberId).eq(MemberStore::getCoinsId, coinsId));
        if (ObjectUtils.isEmpty(store)) {
            throw new CommonException("不存在此货币账户", "member_business_store_not_exist");
        }

        LambdaQueryWrapper<JournalAccount> queryWrapper = new QueryWrapper<JournalAccount>().lambda();
//        queryWrapper.notIn(JournalAccount::getJaType, MemberJAType.getMemberJAWithoutType());
        queryWrapper.eq(JournalAccount::getMemberId, memberId).eq(JournalAccount::getCoinsId, coinsId);

        SysConfig config = configMap.get(ConfigConstants.MEMBER_STORE_MEASURE_NUM);
        if (!ObjectUtils.isEmpty(config) && Integer.parseInt(config.getConfValue()) > 0) {
            queryWrapper.last(" limit " + config.getConfValue());
        }
        queryWrapper.orderByDesc(JournalAccount::getId);
        List<JournalAccount> jaList = memberJAService.list(queryWrapper);
        config = configMap.get(ConfigConstants.MEMBER_STORE_MEASURE_ERROR_LIMIT);
        BigDecimal errorNum = BigDecimal.TEN;
        if (!ObjectUtils.isEmpty(config)) {
            errorNum = BigDecimal.valueOf(Long.parseLong(config.getConfValue()));
        }

        return check(jaList, store, errorNum);
    }

    private boolean check(List<JournalAccount> jaList, MemberStore store, BigDecimal errorNum) {
        if (ObjectUtils.isEmpty(jaList)) {
            return true;
        }
        MemberStore now = ModelMapperUtil.map(store, MemberStore.class);
        if (isInvalidNumber(jaList.get(0), now, errorNum)) {
            return false;
        }
        MemberJAType jaType = MemberJAType.valueOf(jaList.get(0).getJaType());
        if (ObjectUtils.isEmpty(jaType)) {
            return false;
        }

        getNowStore(jaList.get(0), now, jaType);
        jaList.remove(0);
        for (JournalAccount item : jaList) {
            jaType = MemberJAType.valueOf(item.getJaType());
            if (ObjectUtils.isEmpty(jaType)) {
                return false;
            }
            if(isInvalidNumber(item, now, errorNum)){
                log.error("错误流水<id:{}>", item.getId());
                return false;
            }
            getNowStore(item, now, jaType);
        }
        return true;
    }

    private void getNowStore(JournalAccount item, MemberStore now, MemberJAType jaType){
        jaType.doReturnOptStore(now, item.getJaNum());
    }

    private BigDecimal getNowNum(JournalAccount item, BigDecimal nowNum, MemberJAType jaType){
        return jaType.doReturnNum(nowNum, item.getJaNum());
    }

    private BigDecimal getNowFrostNum(JournalAccount item, BigDecimal nowNum, MemberJAType jaType){
        return jaType.doReturnFrostNum(nowNum, item.getJaNum());
    }

    private boolean isInvalidNumber(JournalAccount currentJA, MemberStore nowStore, BigDecimal numberError) {
        return currentJA.getStoreNum().subtract(nowStore.getNum()).abs().compareTo(numberError) > 0
                || currentJA.getStoreFrostNum().subtract(nowStore.getFrostNum()).abs().compareTo(numberError) > 0 ;
    }

}
